////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    SpinTestData.cpp                                             //
//  Developer:   Tommy Riddle                                                 //
//  Create date: 04/29/2005                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: Class that accumulates data during spin testing.             //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2005 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#ifdef ALLOW_SPIN_TESTING

#include "lib.h"
#include "log.h"
#include "SpinTestMessage.h"
#include "SpinTestData.h"
#include "SlotConn.h"

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CSpinTestData()
//
//	Default constructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CSpinTestData()
{
	m_nNumClientDataSetsReceived = 0;
	m_nNumClientDataSetsAllocated = 0;
	m_nCurrentClientDataSet = 0;
	m_apClientDataSets = NULL;
	m_nNumGameModes = 0;
	m_nSubstNoteID = 0;
	m_aGameModeData = NULL;
	m_nNumBonusGameTypes = 0;
	m_aBonusGameData = NULL;
	m_nTotalBet = 0;
	m_nTotalPayout = 0;
	m_nTotalProgressivePayout = 0;
	m_nTotalLinesPlayed = 0;
	m_nPaidLinesPlayed = 0;
	m_nFreeLinesPlayed = 0;
	m_nPreviousGameMode = (uint8)-1;
	m_dSumPayoutsSquared = 0;
	m_dCurrentPaidSpinPayout = 0;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::~CSpinTestData()
//
//	Virtual destructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::~CSpinTestData()
{
	VerifyTotals();

	for ( int n = 0; n < m_nNumClientDataSetsReceived; n++ )
	{
		delete m_apClientDataSets[ n ];
	}

	delete [] m_apClientDataSets;

	delete [] m_aGameModeData;

	delete [] m_aBonusGameData;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::VerifyTotals
//
//	Diagnostic function that checks to make sure that the totals are correct.
//
////////////////////////////////////////////////////////////////////////////////
void CSpinTestData::VerifyTotals()
{
	uint32 nTotalCheck = m_nTotalProgressivePayout;

	for ( int n = 0; n < m_nNumGameModes; n++ )
	{
		nTotalCheck += m_aGameModeData[ n ].m_nTotalPayout;
	}

	for ( n = 0; n < m_nNumBonusGameTypes; n++ )
	{
		nTotalCheck += m_aBonusGameData[ n ].m_nTotalPayout;
	}

	if ( nTotalCheck != m_nTotalPayout )
	{
		Log::msgError("\x7Spin Test: total payout is invaild!  nTotalCheck: %d  m_nTotalPayout: %d", nTotalCheck, m_nTotalPayout );
	}

	if ( m_nPaidLinesPlayed + m_nFreeLinesPlayed != m_nTotalLinesPlayed )
	{
		Log::msgError("\x7Spin Test: total lines played is invaild!  m_nPaidLinesPlayed:  %d  m_nFreeLinesPlayed:  %d  m_nTotalLinesPlayed:  %d", m_nPaidLinesPlayed, m_nFreeLinesPlayed, m_nTotalLinesPlayed );
	}

	if ( m_dCurrentPaidSpinPayout != 0 )
	{
		Log::msgError("\x7Spin Test: current paid spin payout is invaild!  m_dCurrentPaidSpinPayout:  %lf", m_dCurrentPaidSpinPayout );
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::Initialize
//
//	This function has to be called once after construction and before the
//	object can be used to accumulate data.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::Initialize( uint8 nMaxGameMode, uint8 nMaxPayoutType, uint8 nMaxBonusGameType, uint8 nSubstNoteID, uint8 nNumClientDataSets )
{
	m_nNumGameModes = nMaxGameMode + 1;

	m_nSubstNoteID = nSubstNoteID;

	m_aGameModeData = new CGameModeData[ m_nNumGameModes ];

	for ( int n = 0; n < m_nNumGameModes; n++ )
	{
		m_aGameModeData[ n ].Initialize( nMaxPayoutType );
	}

	m_apClientDataSets = new CClientDataSet*[nNumClientDataSets];

	if ( m_apClientDataSets )
	{
		m_nNumClientDataSetsAllocated = nNumClientDataSets;

		for ( n = 0; n < m_nNumClientDataSetsAllocated; n++ )
		{
			m_apClientDataSets[ n ] = NULL;
		}
	}

	m_nNumBonusGameTypes = nMaxBonusGameType + 1;

	m_aBonusGameData = new CDetailData[ m_nNumBonusGameTypes ];
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::AddClientDataSet
//
//	This function is called to store the new client data set contained in
//	the protocol message.
//
////////////////////////////////////////////////////////////////////////////////

bool8 CSpinTestData::AddClientDataSet( const CSpinTestClientDataMessage* pMsg )
{
	bool8 bRV = false;

	if ( m_nNumClientDataSetsReceived < m_nNumClientDataSetsAllocated )
	{
		m_apClientDataSets[ m_nNumClientDataSetsReceived ] = new CClientDataSet( pMsg );

		m_nNumClientDataSetsReceived++;

		bRV = true;
	}

	return bRV;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::Reset
//
//	This function is called to reset the object to its initial state before
//	each batch of spins.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::Reset()
{
	VerifyTotals();

	m_nCurrentClientDataSet = 0;
	m_nTotalBet = 0;
	m_nTotalPayout = 0;
	m_nTotalProgressivePayout = 0;
	m_nTotalLinesPlayed = 0;
	m_nPaidLinesPlayed = 0;
	m_nFreeLinesPlayed = 0;
	m_nPreviousGameMode = (uint8)-1;
	m_dSumPayoutsSquared = 0;
	m_dCurrentPaidSpinPayout = 0;

	for ( int n = 0; n < m_nNumGameModes; n++ )
	{
		m_aGameModeData[ n ].Reset();
	}

	for ( n = 0; n < m_nNumBonusGameTypes; n++ )
	{
		m_aBonusGameData[ n ].Reset();
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::SendClientData
//
//	This function sends the next set of client data to the gut.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::SendClientData( SlotGuts* pGuts )
{
	if ( m_nNumClientDataSetsReceived )
	{
		if ( m_nCurrentClientDataSet == m_nNumClientDataSetsReceived )
		{
			m_nCurrentClientDataSet = 0;
		}

		CClientDataSet* pData = m_apClientDataSets[ m_nCurrentClientDataSet ];

		pGuts->processClientData( pData->m_nBonusGameType, pData->m_nDataCount, pData->m_aData );

		m_nCurrentClientDataSet++;
	}
	else
	{
		// Just send a single 0.
		int32 data = 0;
		pGuts->processClientData(0, 1, &data);
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::SendSummaryData
//
//	This function is called to send the summary data packet to the client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::SendSummaryData( SlotConnection* pConnection )
{
	pConnection->msgStart();

	// Use placement new to call the constructor using the msg buffer for "this".
	// Note:  DO NOT call delete since we aren't actually allocating any memory.
	// We are simply constructing a CSpinTestSummaryDataMessage object inside
	// a buffer that was already allocated and managed elsewhere.
	#pragma push_macro("new")
	#undef new
	CSpinTestSummaryDataMessage* pMsg = new( pConnection->msgGetBuf() ) CSpinTestSummaryDataMessage;
	#pragma pop_macro("new")

	pMsg->m_nTotalBet = m_nTotalBet;
	pMsg->m_nTotalPayout = m_nTotalPayout;
	pMsg->m_dSumPayoutsSquared = m_dSumPayoutsSquared;
	pMsg->m_nTotalProgressivePayout = m_nTotalProgressivePayout;
	pMsg->m_nTotalLinesPlayed = m_nTotalLinesPlayed;
	pMsg->m_nPaidLinesPlayed = m_nPaidLinesPlayed;
	pMsg->m_nFreeLinesPlayed = m_nFreeLinesPlayed;
	
	pConnection->msgReleaseBuf( sizeof( *pMsg ) );

	pConnection->msgEnd();
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::SendGameModeSummaryData
//
//	This function is called to send a game mode summary data packet to the
//	client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::SendGameModeSummaryData( SlotConnection* pConnection, uint8 nGameMode )
{
	m_aGameModeData[ nGameMode ].SendSummaryData( pConnection );
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::SendPayoutTypeDetailData
//
//	This function is called to send a payout type detail data packet to the
//	client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::SendPayoutTypeDetailData( SlotConnection* pConnection, uint8 nGameMode, uint8 nPayoutType )
{
	m_aGameModeData[ nGameMode ].SendPayoutTypeDetailData( pConnection, nPayoutType );
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::SendBonusGameTypeDetailData
//
//	This function is called to send a payout type detail data packet to the
//	client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::SendBonusGameTypeDetailData( SlotConnection* pConnection, uint8 nBonusGameType )
{
	pConnection->msgStart();

	// Use placement new to call the constructor using the msg buffer for "this".
	// Note:  DO NOT call delete since we aren't actually allocating any memory.
	// We are simply constructing a CSpinTestDetailDataMessage object inside
	// a buffer that was already allocated and managed elsewhere.
	#pragma push_macro("new")
	#undef new
	CSpinTestBonusGameTypeDetailDataMessage* pMsg = new( pConnection->msgGetBuf() ) CSpinTestBonusGameTypeDetailDataMessage;
	#pragma pop_macro("new")

	pMsg->m_nHits = m_aBonusGameData[ nBonusGameType ].m_nHits;
	pMsg->m_nTotalPayout = m_aBonusGameData[ nBonusGameType ].m_nTotalPayout;

	pConnection->msgReleaseBuf( sizeof( *pMsg ) );

	pConnection->msgEnd();
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::AccumulateSpinResults
//
//	This function is called after each spin to accumulate the results.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::AccumulateSpinResults( uint32 nLines, uint32 nBetPerLine, bool bPaidSpinCompleted, SlotSpin* spin )
{
	uint32 nTotalBet = nLines * nBetPerLine;

	if ( m_nPreviousGameMode != spin->getGameModeId() )
	{
		m_aGameModeData[ spin->getGameModeId() ].m_nNumTriggers++;
		m_nPreviousGameMode = spin->getGameModeId();
	}

	m_nTotalLinesPlayed += spin->getSpinLineCount();
	
	if ( spin->getBet() )
	{
		m_nTotalBet += nTotalBet;
		m_nPaidLinesPlayed += spin->getSpinLineCount();
	}
	else
	{
		m_nFreeLinesPlayed += spin->getSpinLineCount();
	}

	for ( uint8 lineidx = 0; lineidx < spin->getSpinLineCount(); lineidx++ )
	{
		const SpinLine* spinLine = spin->getSpinLineAt(lineidx);

        if ( spinLine->jackpot )
		{
			AccumulateProgressive( spinLine->totallinepayoutamount );
		}
		else
		{
			bool8 bSubst = false;

			for ( uint8 noteidx = 0; noteidx < spinLine->getNoteCount(); noteidx++ )
			{
				if ( spinLine->getNote( noteidx ) == m_nSubstNoteID )
				{
					bSubst = true;
					break;
				}
			}

			AccumulatePayout( spin->getGameModeId(), spinLine->payouttypeid, bSubst, spinLine->totallinepayoutamount );
		}
	}

	for ( uint8 scatteridx = 0; scatteridx < spin->getNumScatters(); scatteridx++ )
	{
		const SlotScatter* pScatter = spin->getScatter( scatteridx );

		if ( pScatter->jackpot )
		{
			AccumulateProgressive( pScatter->totalscatterpayoutamount );
		}
		else
		{
			bool8 bSubst = false;

			for ( uint8 noteidx = 0; noteidx < pScatter->getNoteCount(); noteidx++ )
			{
				if ( pScatter->getNote( noteidx ) == m_nSubstNoteID )
				{
					bSubst = true;
					break;
				}
			}

			AccumulatePayout( spin->getGameModeId(), pScatter->payouttypeid, bSubst, pScatter->totalscatterpayoutamount );
		}
	}

	for ( uint8 bonusgameidx = 0; bonusgameidx < spin->getNumBonusGames(); bonusgameidx++ )
	{
		const BonusGame* pBonusGame = spin->getBonusGame( bonusgameidx );

		AccumulateBonusGame( pBonusGame->bonusgametype, pBonusGame->totalbonuspayoutamount );
	}

	if ( bPaidSpinCompleted )
	{
		m_dCurrentPaidSpinPayout /= nBetPerLine;
		m_dSumPayoutsSquared += m_dCurrentPaidSpinPayout * m_dCurrentPaidSpinPayout;
		m_dCurrentPaidSpinPayout = 0;
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::GetNumPaidLinesPlayed
//
//	This function gets the total number of paid lines played during the batch
//	of spins.
//
////////////////////////////////////////////////////////////////////////////////

uint32 CSpinTestData::GetNumPaidLinesPlayed() const
{
	return m_nPaidLinesPlayed;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::AccumulatePayout
//
//	This is a helper function that accumulates results for a specific payout.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::AccumulatePayout( uint8 nGameMode, uint8 nPayoutType, bool8 bSubst, uint32 nTotalPayout )
{
	ASSERT( nGameMode < m_nNumGameModes );

	m_aGameModeData[ nGameMode ].AccumulatePayout( nPayoutType, bSubst, nTotalPayout );

	m_nTotalPayout += nTotalPayout;
	m_dCurrentPaidSpinPayout += nTotalPayout;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::AccumulateBonusGame
//
//	This is a helper function that accumulates results for a bonus game.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::AccumulateBonusGame( uint8 nBonusGameType, uint32 nTotalPayout )
{
	ASSERT( nBonusGameType < m_nNumBonusGameTypes );

	m_aBonusGameData[ nBonusGameType ].AccumulatePayout( nTotalPayout );

	m_nTotalPayout += nTotalPayout;
	m_dCurrentPaidSpinPayout += nTotalPayout;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::AccumulateProgressive
//
//	This is a helper function that accumulates results for a progessive win.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::AccumulateProgressive( uint32 nTotalPayout )
{
	m_nTotalProgressivePayout += nTotalPayout;
	m_nTotalPayout += nTotalPayout;
	m_dCurrentPaidSpinPayout += nTotalPayout;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CClientDataSet::CClientDataSet
//
//	Default constructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CClientDataSet::CClientDataSet( const CSpinTestClientDataMessage* pMsg )
{
	m_nBonusGameType = pMsg->m_byBonusGameType;

	m_aData = new int32[ pMsg->m_byDataCount ];

	if ( m_aData )
	{
		m_nDataCount = pMsg->m_byDataCount;

		for ( int n = 0; n < m_nDataCount; n++ )
		{
			m_aData[ n ] = pMsg->m_adwData[ n ];
		}
	}
	else
	{
		m_nDataCount = 0;
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CClientDataSet::~CClientDataSet
//
//	Virtual destructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CClientDataSet::~CClientDataSet()
{
	delete [] m_aData;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::CGameModeData
//
//	Default constructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CGameModeData::CGameModeData()
{
	m_nNumPayoutTypes = 0;

	m_aPayoutDataNoSubst = NULL;
	m_aPayoutDataWithSubst = NULL;

	m_nTotalPayout = 0;

	m_nNumTriggers = 0;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::~CGameModeData
//
//	Virtual destructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CGameModeData::~CGameModeData()
{
	VerifyTotal();

	delete [] m_aPayoutDataNoSubst;
	delete [] m_aPayoutDataWithSubst;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::VerifyTotal
//
//	Diagnostic function that checks to make sure that the total is correct.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::VerifyTotal()
{
	uint32 nTotalCheck = 0;

	for ( int n = 0; n < m_nNumPayoutTypes; n++ )
	{
		nTotalCheck += m_aPayoutDataNoSubst[ n ].m_nTotalPayout;
		nTotalCheck += m_aPayoutDataWithSubst[ n ].m_nTotalPayout;
	}

	if ( nTotalCheck != m_nTotalPayout )
	{
		Log::msgError("\x7Spin Test: game mode total is invaild for game mode: 0x%08X  nTotalCheck: %d  m_nTotalPayout: %d", this, nTotalCheck, m_nTotalPayout);
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::Initialize
//
//	This function has to be called once after construction and before the
//	object can be used to accumulate data.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::Initialize( uint8 nMaxPayoutType )
{
	m_nNumPayoutTypes = nMaxPayoutType + 1;

	m_aPayoutDataNoSubst = new CDetailData[ m_nNumPayoutTypes ];
	m_aPayoutDataWithSubst = new CDetailData[ m_nNumPayoutTypes ];
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::Reset
//
//	This function is called to reset the object to its initial state
//	before each batch of spins.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::Reset()
{
	VerifyTotal();

	m_nTotalPayout = 0;

	m_nNumTriggers = 0;

	for ( int n = 0; n < m_nNumPayoutTypes; n++ )
	{
		m_aPayoutDataNoSubst[ n ].Reset();
		m_aPayoutDataWithSubst[ n ].Reset();
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::SendSummaryData
//
//	This function is called to send a game mode summary data packet to the client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::SendSummaryData( SlotConnection* pConnection )
{
	pConnection->msgStart();

	// Use placement new to call the constructor using the msg buffer for "this".
	// Note:  DO NOT call delete since we aren't actually allocating any memory.
	// We are simply constructing a CSpinTestDetailDataMessage object inside
	// a buffer that was already allocated and managed elsewhere.
	#pragma push_macro("new")
	#undef new
	CSpinTestGameModeSummaryDataMessage* pMsg = new( pConnection->msgGetBuf() ) CSpinTestGameModeSummaryDataMessage;
	#pragma pop_macro("new")

	pMsg->m_nTotalPayout = m_nTotalPayout;
	pMsg->m_nNumTriggers = m_nNumTriggers;

	pConnection->msgReleaseBuf( sizeof( *pMsg ) );

	pConnection->msgEnd();
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::SendPayoutTypeDetailData
//
//	This function is called to send a payout type detail data packet to the
//	client.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::SendPayoutTypeDetailData( SlotConnection* pConnection, uint8 nPayoutType )
{
	pConnection->msgStart();

	// Use placement new to call the constructor using the msg buffer for "this".
	// Note:  DO NOT call delete since we aren't actually allocating any memory.
	// We are simply constructing a CSpinTestDetailDataMessage object inside
	// a buffer that was already allocated and managed elsewhere.
	#pragma push_macro("new")
	#undef new
	CSpinTestPayoutTypeDetailDataMessage* pMsg = new( pConnection->msgGetBuf() ) CSpinTestPayoutTypeDetailDataMessage;
	#pragma pop_macro("new")

	pMsg->m_nHitsNoSubst = m_aPayoutDataNoSubst[ nPayoutType ].m_nHits;
	pMsg->m_nPayoutNoSubst = m_aPayoutDataNoSubst[ nPayoutType ].m_nTotalPayout;
	pMsg->m_nHitsWithSubst = m_aPayoutDataWithSubst[ nPayoutType ].m_nHits;
	pMsg->m_nPayoutWithSubst = m_aPayoutDataWithSubst[ nPayoutType ].m_nTotalPayout;

	pConnection->msgReleaseBuf( sizeof( *pMsg ) );

	pConnection->msgEnd();
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CGameModeData::AccumulatePayout
//
//	This function is called to accumulate results for a specific payout
//	type.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CGameModeData::AccumulatePayout( uint8 nPayoutType, bool8 bSubst, uint32 nTotalPayout )
{
	ASSERT( nPayoutType < m_nNumPayoutTypes );

	if ( bSubst )
	{
		m_aPayoutDataWithSubst[ nPayoutType ].AccumulatePayout( nTotalPayout );
	}
	else
	{
		m_aPayoutDataNoSubst[ nPayoutType ].AccumulatePayout( nTotalPayout );
	}

	m_nTotalPayout += nTotalPayout;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CDetailData::CDetailData
//
//	Default constructor.
//
////////////////////////////////////////////////////////////////////////////////

CSpinTestData::CDetailData::CDetailData()
{
	m_nHits = 0;
	m_nTotalPayout = 0;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CDetailData::Reset
//
//	This function is called to reset the payout to its initial state
//	before each batch of spins.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CDetailData::Reset()
{
	m_nHits = 0;
	m_nTotalPayout = 0;
}

////////////////////////////////////////////////////////////////////////////////
//
//	CSpinTestData::CDetailData::AccumulatePayout
//
//	This function is called to add the passed in payout to the accumulated total.
//
////////////////////////////////////////////////////////////////////////////////

void CSpinTestData::CDetailData::AccumulatePayout( uint32 nTotalPayout )
{
	m_nHits++;
	m_nTotalPayout += nTotalPayout;
}

#endif